from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django.utils import timezone
from .models import (
    Project,
    Environment,
    ApiInterface,
    TestCase,
    TestExecution,
    TestReport
)
from .serializers import (
    ProjectSerializer,
    EnvironmentSerializer,
    ApiInterfaceSerializer,
    TestCaseSerializer,
    TestExecutionSerializer,
    TestReportSerializer
)
from .core.test_engine import TestExecutionEngine
from django.views.generic import ListView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, FileResponse
from django.views import View
from .core.report_generator import ReportGenerator
import os
from django.conf import settings
from django.http import JsonResponse
from django.http import HttpResponseBadRequest, HttpResponseNotFound, HttpResponseServerError


class ProjectViewSet(viewsets.ModelViewSet):
    """
    项目管理视图集
    """
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据用户过滤项目"""
        return Project.objects.filter(creator=self.request.user)


class EnvironmentViewSet(viewsets.ModelViewSet):
    """
    环境管理视图集
    """
    queryset = Environment.objects.all()
    serializer_class = EnvironmentSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据项目过滤环境"""
        project_id = self.request.query_params.get('project', None)
        queryset = Environment.objects.all()
        if project_id:
            queryset = queryset.filter(project_id=project_id)
        return queryset


class ApiInterfaceViewSet(viewsets.ModelViewSet):
    """
    接口管理视图集
    """
    queryset = ApiInterface.objects.all()
    serializer_class = ApiInterfaceSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据项目过滤接口"""
        project_id = self.request.query_params.get('project', None)
        queryset = ApiInterface.objects.all()
        if project_id:
            queryset = queryset.filter(project_id=project_id)
        return queryset


class TestCaseViewSet(viewsets.ModelViewSet):
    """
    测试用例视图集
    """
    queryset = TestCase.objects.all()
    serializer_class = TestCaseSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据接口过滤测试用例"""
        interface_id = self.request.query_params.get('interface', None)
        queryset = TestCase.objects.all()
        if interface_id:
            queryset = queryset.filter(interface_id=interface_id)
        return queryset

    @action(detail=True, methods=['post'])
    def execute(self, request, pk=None):
        """执行测试用例"""
        test_case = self.get_object()
        environment_id = request.data.get('environment')
        
        if not environment_id:
            return Response({'error': '请指定执行环境'}, status=400)
            
        try:
            environment = Environment.objects.get(id=environment_id)
        except Environment.DoesNotExist:
            return Response({'error': '指定的环境不存在'}, status=404)
            
        # 使用测试执行引擎
        engine = TestExecutionEngine(
            test_case=test_case,
            environment=environment,
            executor=request.user
        )
        
        # 执行测试用例
        execution = engine.execute()
        
        return Response(TestExecutionSerializer(execution).data)

    @action(detail=False, methods=['post'])
    def batch_execute(self, request):
        """批量执行测试用例"""
        test_case_ids = request.data.get('test_cases', [])
        environment_id = request.data.get('environment')
        
        if not environment_id:
            return Response({'error': '请指定执行环境'}, status=400)
            
        try:
            environment = Environment.objects.get(id=environment_id)
        except Environment.DoesNotExist:
            return Response({'error': '指定的环境不存在'}, status=404)
            
        if not test_case_ids:
            return Response({'error': '请指定要执行的测试用例'}, status=400)
            
        executions = []
        for test_case_id in test_case_ids:
            try:
                test_case = TestCase.objects.get(id=test_case_id)
                engine = TestExecutionEngine(
                    test_case=test_case,
                    environment=environment,
                    executor=request.user
                )
                execution = engine.execute()
                executions.append(execution)
            except TestCase.DoesNotExist:
                continue
                
        # 创建测试报告
        total_cases = len(executions)
        passed_cases = sum(1 for e in executions if e.result == 'pass')
        failed_cases = sum(1 for e in executions if e.result == 'fail')
        error_cases = sum(1 for e in executions if e.result == 'error')
        skipped_cases = 0
        
        report = TestReport.objects.create(
            name=f"批量测试报告 - {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}",
            project=environment.project,
            creator=request.user,
            start_time=min(e.start_time for e in executions) if executions else timezone.now(),
            end_time=max(e.end_time for e in executions) if executions else timezone.now(),
            total_cases=total_cases,
            passed_cases=passed_cases,
            failed_cases=failed_cases,
            error_cases=error_cases,
            skipped_cases=skipped_cases,
            summary=f"总用例数: {total_cases}\n"
                   f"通过: {passed_cases}\n"
                   f"失败: {failed_cases}\n"
                   f"错误: {error_cases}\n"
                   f"跳过: {skipped_cases}"
        )
        
        # 关联执行记录
        report.executions.set(executions)
        
        return Response({
            'message': f'成功执行 {len(executions)} 个测试用例',
            'report_id': report.id,
            'executions': TestExecutionSerializer(executions, many=True).data
        })


class TestExecutionViewSet(viewsets.ModelViewSet):
    """
    测试执行记录视图集
    """
    queryset = TestExecution.objects.all()
    serializer_class = TestExecutionSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据测试用例过滤执行记录"""
        test_case_id = self.request.query_params.get('test_case', None)
        queryset = TestExecution.objects.all()
        if test_case_id:
            queryset = queryset.filter(test_case_id=test_case_id)
        return queryset


class TestReportViewSet(viewsets.ModelViewSet):
    """
    测试报告视图集
    """
    queryset = TestReport.objects.all()
    serializer_class = TestReportSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """根据项目过滤测试报告"""
        project_id = self.request.query_params.get('project', None)
        queryset = TestReport.objects.all()
        if project_id:
            queryset = queryset.filter(project_id=project_id)
        return queryset


class ReportListView(LoginRequiredMixin, ListView):
    """测试报告列表视图"""
    model = TestReport
    template_name = 'api_manager/report_list.html'
    context_object_name = 'reports'
    paginate_by = 10
    
    def get_queryset(self):
        """获取报告列表"""
        queryset = TestReport.objects.all()
        
        # 按项目筛选
        project_id = self.request.GET.get('project')
        if project_id:
            queryset = queryset.filter(project_id=project_id)
            
        # 按时间范围筛选
        start_date = self.request.GET.get('start_date')
        end_date = self.request.GET.get('end_date')
        if start_date:
            queryset = queryset.filter(created_time__gte=start_date)
        if end_date:
            queryset = queryset.filter(created_time__lte=end_date)
            
        return queryset.order_by('-created_time')
        
    def get_context_data(self, **kwargs):
        """获取上下文数据"""
        context = super().get_context_data(**kwargs)
        context['projects'] = Project.objects.all()
        return context


class ReportDetailView(LoginRequiredMixin, DetailView):
    """测试报告详情视图"""
    model = TestReport
    template_name = 'api_manager/report_detail.html'
    context_object_name = 'report'
    
    def get_context_data(self, **kwargs):
        """获取上下文数据"""
        context = super().get_context_data(**kwargs)
        report = self.get_object()
        
        # 获取执行记录
        executions = report.executions.all().select_related('test_case', 'test_case__interface')
        
        # 生成测试结果统计
        total = len(executions)
        passed = sum(1 for exe in executions if exe.result == 'pass')
        failed = sum(1 for exe in executions if exe.result == 'fail')
        error = sum(1 for exe in executions if exe.result == 'error')
        skipped = sum(1 for exe in executions if exe.result == 'skip')
        
        context.update({
            'total_cases': total,
            'passed_cases': passed,
            'failed_cases': failed,
            'error_cases': error,
            'skipped_cases': skipped,
            'pass_rate': f"{(passed / total * 100):.2f}%" if total > 0 else "0%",
            'executions': executions,
            'duration': (report.end_time - report.start_time).total_seconds()
        })
        
        return context


class ReportExportView(View):
    def get(self, request, pk, format=None):
        try:
            report = TestReport.objects.get(pk=pk)
            
            # 获取导出格式
            export_format = format or 'pdf'
            
            if export_format == 'pdf':
                # 生成PDF报告
                generator = ReportGenerator(report)
                pdf_path = generator.export_pdf(os.path.join(settings.MEDIA_ROOT, 'reports'))
                
                # 返回PDF文件
                response = FileResponse(
                    open(pdf_path, 'rb'),
                    content_type='application/pdf'
                )
                response['Content-Disposition'] = f'attachment; filename="{os.path.basename(pdf_path)}"'
                return response
                
            elif export_format == 'html':
                # 生成HTML报告
                generator = ReportGenerator(report)
                context = {
                    'report': generator.generate_summary(),
                    'executions': generator.generate_execution_details()
                }
                return render(request, 'api_manager/report_template.html', context)
                
            elif export_format == 'json':
                # 返回JSON格式的报告数据
                generator = ReportGenerator(report)
                data = {
                    'summary': generator.generate_summary(),
                    'executions': generator.generate_execution_details()
                }
                return JsonResponse(data)
                
            else:
                return HttpResponseBadRequest('不支持的导出格式')
                
        except TestReport.DoesNotExist:
            return HttpResponseNotFound('报告不存在')
        except Exception as e:
            return HttpResponseServerError(f'导出报告时发生错误: {str(e)}')
